package com.example.demo.controller;

import com.example.demo.common.constant.JwtClaimsConstant;
import com.example.demo.common.constant.RedisConstants;
import com.example.demo.pojo.entity.GenerateHistory;
import com.example.demo.pojo.entity.Result;

import com.example.demo.service.GenerateService;
import com.example.demo.utils.BaseContext;
import com.example.demo.utils.JwtProperties;
import com.example.demo.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.SSEResponseModel;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
// import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.hunyuan.v20230901.HunyuanClient;
import com.tencentcloudapi.hunyuan.v20230901.models.*;

import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
public class GenerateController {
    @Autowired
    private GenerateService generateService;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private JwtProperties jwtProperties;

    @PostMapping("/api/generate")
    public Result generate(String style, String prompt, Long taskId) {
        // 获取 token
        String token = request.getHeader(jwtProperties.getUserTokenName());
        if (token == null) {
            return Result.error("未提供 token");
        }

        // 解析 token，判断是否为试用 token
        Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
        Integer trialFlag = (Integer) claims.get(JwtClaimsConstant.TRIAL);
        boolean isTrialToken = trialFlag != null && trialFlag == 1;

        // 如果是试用 token，检查调用次数
        if (isTrialToken) {
            String key = RedisConstants.TRIAL_KEY + token;
            String countStr = (String) redisTemplate.opsForValue().get(key);
            // 若未记录，则初始化为 0
            if (countStr == null) {
                redisTemplate.opsForValue().set(key, "0");
                redisTemplate.expire(key, RedisConstants.TRIAL_TTL, TimeUnit.SECONDS);
                countStr = "0";
            }
            Integer count = Integer.parseInt(countStr);
            if (count != null && count >= 5) {
                return Result.error("试用次数已用完，请登录或注册账号");
            }
            // 增加计数(字符串递增)
            redisTemplate.opsForValue().increment(key);
        }

        log.info("开始生成图片，风格：{}，提示词：{}", style, prompt);
        // 1. 生成标题内容标签
        String textContent = generateText(style, prompt);
        if (textContent == null) {
            return Result.error("文本生成失败");
        }
        // 2. 解析返回结果，提取标题、正文、标签
        String[] parts = textContent.split("\n");
        String title = "";
        String content = "";
        String tags = "";
        boolean isTitleFound = false;
        boolean isContentFound = false;
        boolean isTagsFound = false;
        for (int i = 0; i < parts.length; i++) {
            String line = parts[i];
            if (line.trim().isEmpty()) {
                continue;
            }
            if (line.startsWith("标题：")) {
                title = line.substring(3).trim();
                isTitleFound = true;
            } else if (line.startsWith("正文：")) {
                content = line.substring(3).trim();
                isContentFound = true;
            } else if (line.startsWith("标签：")) {
                tags = line.substring(3).trim();
                isTagsFound = true;
            } else if (isTagsFound) {
                tags += " " + line.trim();
            } else if (isContentFound) {
                content += (content.isEmpty() ? "" : "\n") + line.trim();
            } else if (isTitleFound) {
                title += line.trim();
            }
        }
        // 3. 生成封面图片
        String imageUrl = generateImage(style, prompt);
        if (imageUrl == null) {
            return Result.error("图片生成失败");
        }
        //4. 存储结果到数据库
        GenerateHistory history = new GenerateHistory();
        history.setTaskId(taskId);
        history.setTitle(title);
        history.setContent(content);
        history.setTags(tags);
        history.setCoverImageUrl(imageUrl);
        if (BaseContext.getCurrentId() != null && taskId != null) {
            generateService.save(history);
        }
        //5. 返回结果(GenerateHistory)
        return Result.success(history);
    }

    private String generateImage(String style, String prompt) {
        // 文档 https://cloud.tencent.com/document/api/1729/105701
        Credential cred = new Credential(System.getProperty("TENCENTCLOUD_SECRET_ID"), System.getProperty("TENCENTCLOUD_SECRET_KEY"));
        // 实例化一个http选项，可选的，没有特殊需求可以跳过
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setEndpoint("hunyuan.tencentcloudapi.com");
        // 实例化一个client选项，可选的，没有特殊需求可以跳过
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        // 实例化要请求产品的client对象,clientProfile是可选的
        HunyuanClient client = new HunyuanClient(cred, "ap-guangzhou", clientProfile);
        // 实例化一个请求对象,每个接口都会对应一个request对象
        TextToImageLiteRequest req = new TextToImageLiteRequest();
        req.setPrompt("请为小红书笔记生成一个高质量的封面图，风格为" + style + "，内容主题是：" + prompt);
        req.setResolution("768:768");
        req.setLogoAdd(0L);
        req.setRspImgType("base64");
        // 返回的resp是一个TextToImageLiteResponse的实例，与请求对象对应
        try {
            TextToImageLiteResponse resp = client.TextToImageLite(req);
            return resp.getResultImage();
        } catch (Exception e) {
            log.error("生成图片时发生错误: {}", e.getMessage(), e);
            return null;
        }
    }

    private String generateText(String style, String prompt) {
        // 文档 https://cloud.tencent.com/document/api/1729/108738
        Credential cred = new Credential(System.getProperty("TENCENTCLOUD_SECRET_ID"), System.getProperty("TENCENTCLOUD_SECRET_KEY"));
        // 实例化一个http选项，可选的，没有特殊需求可以跳过
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setEndpoint("hunyuan.tencentcloudapi.com");
        // 实例化一个client选项，可选的，没有特殊需求可以跳过
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        // 实例化要请求产品的client对象,clientProfile是可选的
        HunyuanClient client = new HunyuanClient(cred, "", clientProfile);
        // 实例化一个请求对象,每个接口都会对应一个request对象
        ChatCompletionsRequest req = new ChatCompletionsRequest();
        req.setModel("hunyuan-standard");

        Message[] messages1 = new Message[2];
        Message message1 = new Message();
        message1.setRole("system");
        message1.setContent(
            "你是一名专业的小红书内容创作者，擅长根据用户提供的主题和风格，生成符合小红书爆款特征的标题、正文内容和标签。\n" +
            "\n" +
            "生成要求：\n" +
            "1. 标题：简短、有吸引力、带情绪或好奇点，贴合小红书爆款标题风格。\n" +
            "2. 正文：使用自然、口语化、真诚的语气，可加入 emoji，分段清晰，内容真实可信。\n" +
            "3. 标签：生成 3～6 个带 # 的标签，贴合内容主题和风格。\n" +
            "4. 输出时不要包含任何解释或系统说明，只输出最终结果。\n" +
            "\n" +
            "输出格式：\n" +
            "标题：\n" +
            "正文：\n" +
            "标签："
        );
        messages1[0] = message1;

        Message message2 = new Message();
        message2.setRole("user");
        message2.setContent("用户内容提示：" + prompt + "\n生成风格：" + style);
        messages1[1] = message2;

        req.setMessages(messages1);

        req.setStream(false);
        // 返回的resp是一个ChatCompletionsResponse的实例，与请求对象对应
        try {
            ChatCompletionsResponse resp = client.ChatCompletions(req);
            String result = resp.getChoices()[0].getMessage().getContent();
            return result;
        } catch (Exception e) {
            log.error("生成文本时发生错误: {}", e.getMessage(), e);
            return null;
        }
    }
}
